<?php
/**
 * Created by PhpStorm.
 * User: bililovy
 * Date: 19-7-5
 * Time: 上午11:08
 * Description:
 */

namespace ServiceSdk\Utils\Encrypt;

use ServiceSdk\Services\BaseService;

class RC4 extends BaseService
{
    private static $fixKey;

    /**
     * Description: 加密和加密文本
     *
     * @param string $privateKey 加密密钥
     * @param string $data       要加密、解密的数据（必须为字符串）
     *
     * @return string
     * @Author: Bililovy
     * @Date  : 19-7-5 上午11:22
     */
    public static function crypt(string $data, string $privateKey = ''): string
    {
        self::setKey($privateKey);

        return self::doCrypt($data);
    }

    /**
     * Description: RC4算法 加解密，加解密均用此方法
     *
     * @param string $data 要加解密的字符串或密文
     *
     * @return string
     * @Author: Bililovy
     * @Date  : 19-7-5 上午11:15
     */
    private static function doCrypt(string $data): string
    {
        $strLen = strlen($data);
        $a = 0;
        $b = 0;
        $cipher = '';
        for ($i = 0; $i < $strLen; $i++) {
            $a = ($a + 1) & 255;
            $b = ($b + self::$fixKey[$a]) & 255;
            self::swap(self::$fixKey[$a], self::$fixKey[$b]);
            $k = self::$fixKey[(self::$fixKey[$a] + self::$fixKey[$b]) & 255];
            $cipher .= chr(ord($data[$i]) ^ $k);
        }

        return $cipher;
    }

    /**
     * Description: 根据传入的密钥 传入
     *
     * @param $pwd
     *
     * @Author: Bililovy
     * @Date  : 19-7-5 上午11:22
     */
    private static function setKey($pwd)
    {
        for ($i = 0; $i < 256; $i++) {
            self::$fixKey[$i] = $i;
        }

        $j = 0;
        $keyLen = strlen($pwd);
        for ($i = 0; $i < 256; ++$i) {
            $j = (self::$fixKey[$i] + ord($pwd[$i % $keyLen]) + $j) & 255;
            self::swap(self::$fixKey[$i], self::$fixKey[$j]);
        }
    }

    /**
     * Description: 交换变量
     *
     * @param $left
     * @param $right
     *
     * @Author: Bililovy
     * @Date  : 19-7-5 上午11:16
     */
    private static function swap(&$left, &$right)
    {
        list($left, $right) = [$right, $left];
    }

}